﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace Qiang.Data
{
    public class ShapeList : IShapeList
    {


        #region 初始化

        public ShapeList()
        {
            Configure();
        }

        public ShapeList(IDataset parent)
        {
            this._parentDataset = parent;
            Configure();
        }


        void Configure()
        {
            _innerList = new List<IShape>();
        }


        #endregion


        #region 事件

        /// <summary>
        /// 图形添加事件
        /// </summary>
        public event EventHandler<ShapeEventArgs> ShapeAdded;

        /// <summary>
        /// 图形删除事件
        /// </summary>
        public event EventHandler<ShapeEventArgs> ShapeRemoved;

        #endregion


        #region 字段

        private List<IShape> _innerList;

        private IDataset _parentDataset;

        private bool _eventsSuspended;

        #endregion


        #region 属性


        /// <summary>
        /// 所属数据集
        /// </summary>
        public IDataset ParentDataset
        {
            get
            {
                return _parentDataset;
            }
        }


        /// <summary>
        /// 指示此集合是否是只读
        /// </summary>
        public bool IsReadOnly
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// 指示事件是否挂起
        /// </summary>
        public bool EventsSuspended
        {
            get
            {
                return _eventsSuspended;
            }
        }

        /// <summary>
        /// 集合条目的数量
        /// </summary>
        public virtual int Count
        {
            get
            {
                return _innerList.Count;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public virtual IShape this[int index]
        {
            get
            {
                return _innerList[index];
            }
            set
            {
                ExcludeShape(_innerList[index]);
                _innerList[index] = value;
                IncludeShape(value);
            }
        }

        #endregion


        #region 方法

        /// <summary>
        /// 挂起事件。使事件不可触发
        /// </summary>
        public void SuspendEvent()
        {
            _eventsSuspended = true;
        }

        /// <summary>
        /// 恢复挂起事件。使事件可触发
        /// </summary>
        public void ResumeEvents()
        {
            _eventsSuspended = false;
        }

        /// <summary>
        /// 生成图形集合。
        /// </summary>
        /// <returns></returns>
        public List<IShape> ToList()
        {
            return _innerList;
        }

        #region 添加

        /// <summary>
        /// 添加图形
        /// </summary>
        /// <param name="shp"></param>
        public virtual void Add(IShape shp)
        {
            if (_innerList.Contains(shp)) return;
            switch (shp.ShapeType)
            {
                case ShapeType.Node:
                    AddNode(shp as INodeShape);
                    break;
                case ShapeType.Segment:
                    AddSegment(shp as ISegmentShape);
                    break;
                case ShapeType.Polygon:
                    AddPolygon(shp as IPolygonShape);
                    break;
                default:
                    break;
            }
            IncludeShape(shp);
        }


        /// <summary>
        /// 包含图形
        /// </summary>
        /// <param name="shp"></param>
        void IncludeShape(IShape shp)
        {            
            shp.ParentDataset = _parentDataset;
            OnShapeAdded(shp);
        }


        void AddNode(INodeShape node)
        {
            if (_innerList.Contains(node)) return;
            _innerList.Add(node);
        }

        void AddSegment(ISegmentShape segment)
        {
            if (_innerList.Contains(segment)) return;            
            Add(segment.StartNode);
            Add(segment.EndNode);

            if (segment.StartNode.SegmentCollection.Contains(segment) == false)
                segment.StartNode.SegmentCollection.Add(segment);

            if (segment.EndNode.SegmentCollection.Contains(segment) == false)
                segment.EndNode.SegmentCollection.Add(segment);
            _innerList.Add(segment);
        }

        void AddPolygon(IPolygonShape polygon)
        {
            if (_innerList.Contains(polygon)) return;            
            foreach (ISegmentShape segment in polygon.Shell.Segments)
            {
                Add(segment);
            }
            foreach (IPart hole in polygon.Holes)
            {
                foreach (ISegmentShape segment in hole.Segments)
                {
                    Add(segment);
                }
            }
            _innerList.Add(polygon);
        }


        /// <summary>
        /// 当添加图形时，引发图形添加事件。
        /// </summary>
        /// <param name="shp"></param>
        protected virtual void OnShapeAdded(IShape shp)
        {
            //如果事件挂起，不触发事件
            if (_eventsSuspended == true) return;
            if (ShapeAdded != null)
            {
                ShapeAdded(this, new ShapeEventArgs(shp));
            }
        }

        #endregion


        #region 删除

        /// <summary>
        /// 删除图形
        /// </summary>
        /// <param name="shp"></param>
        public virtual bool Remove(IShape shp)
        {
            if (!_innerList.Contains(shp)) return true;
            switch (shp.ShapeType)
            {
                case ShapeType.Node:
                    INodeShape node = shp as INodeShape;
                    return RemoveNode(node);
                case ShapeType.Segment:
                    ISegmentShape segment = shp as ISegmentShape;
                    return RemoveSegment(segment);
                case ShapeType.Polygon:
                    IPolygonShape polygon = shp as IPolygonShape;
                    return RemovePolygon(polygon);
                default:
                    return true;
            }           
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="node"></param>
        public virtual bool RemoveNode(INodeShape node)
        {
            if (!_innerList.Contains(node)) return true;
            int count = node.SegmentCollection.Count;
            for (int i = count - 1; i >= 0; i--)
            {
                RemoveSegment(node.SegmentCollection[i]);
            }          
            if (_innerList.Remove(node))
            {
                ExcludeShape(node);
                return true;
            }
            return false;
        }

        public virtual bool RemoveSegment(ISegmentShape segment)
        {
            if (!_innerList.Contains(segment)) return true;
            if (segment.LeftPolygon != null) RemovePolygon(segment.LeftPolygon);
            if (segment.RightPolygon != null) RemovePolygon(segment.RightPolygon);
            if (segment.StartNode.SegmentCollection.Contains(segment))
                segment.StartNode.SegmentCollection.Remove(segment);
            if (segment.EndNode.SegmentCollection.Contains(segment))
                segment.EndNode.SegmentCollection.Remove(segment);
            if (_innerList.Remove(segment))
            {
                ExcludeShape(segment);
                return true;
            }
            return false;
        }

        public virtual bool RemovePolygon (IPolygonShape polygon)
        {
            if (!_innerList.Contains(polygon)) return false;
            foreach (DirectionalSegment dirSegment in polygon.Shell.SegmentCollection)
            {
                RemoveRelationship(dirSegment, polygon);
            }
            foreach (IPart hole in polygon.Holes)
            {
                foreach (DirectionalSegment dirSegment in hole.SegmentCollection)
                {
                    RemoveRelationship(dirSegment, polygon);
                }
            }
            if (_innerList.Remove(polygon))
            {
                ExcludeShape(polygon);
                return true;
            }
            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="segment"></param>
        /// <param name="polygon"></param>
        void RemoveRelationship(DirectionalSegment DirSegment, IPolygonShape polygon)
        {
            if (polygon.Equals(DirSegment.Segment.LeftPolygon))
            {
                DirSegment.Segment.LeftPolygon = null;
            }
            else if (polygon.Equals(DirSegment.Segment.RightPolygon))
            {
                DirSegment.Segment.RightPolygon = null;
            }
            else
            {
                throw new Exception("两者不存在拓扑关系!");
            }
            DirSegment.Segment.UsedNum -= 1;
            if (DirSegment.Segment.UsedNum == 1)
            {
                if (DirSegment.Derection == DirSegment.Segment.FirstusedDerection)
                    DirSegment.Segment.FirstusedDerection = DirectionReverse.Reverse(DirSegment.Derection);
            }
        }

        
        /// <summary>
        /// 删除某一位置的图形
        /// </summary>
        /// <param name="index"></param>
        public virtual void RemoveAt(int index)
        {
            IShape shp = _innerList[index];
            ExcludeShape(shp);
            _innerList.RemoveAt(index);
        }
        

        /// <summary>
        /// 去除图形
        /// </summary>
        /// <param name="shp"></param>
        void ExcludeShape(IShape shp)
        {
            shp.ParentDataset = null;
            OnShapeRemoved(shp);
        }


        /// <summary>
        /// 当删除图形时，引发图形删除事件
        /// </summary>
        /// <param name="shp"></param>
        protected virtual void OnShapeRemoved(IShape shp)
        {
            if (_eventsSuspended == true) return;
            if (ShapeRemoved != null)
            {
                ShapeRemoved(this, new ShapeEventArgs(shp));
            }
        }

        #endregion


        #region 插入

        /// <summary>
        /// 插入图形
        /// </summary>
        /// <param name="index"></param>
        /// <param name="shp"></param>
        public virtual void Insert(int index,IShape shp)
        {
            _innerList.Insert(index, shp);
            IncludeShape(shp);
        }

        #endregion


        #region CopyTo

        /// <summary>
        /// 
        /// </summary>
        /// <param name="array"></param>
        /// <param name="arrayIndex"></param>
        public virtual void CopyTo(IShape[] array, int arrayIndex)
        {
            _innerList.CopyTo(array, arrayIndex);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="index"></param>
        /// <param name="array"></param>
        /// <param name="arrayIndex"></param>
        /// <param name="count"></param>
        public virtual void CopyTo(int index, IShape[] array, int arrayIndex, int count)
        {
            _innerList.CopyTo(index, array, arrayIndex, count);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="array"></param>
        public virtual void CopyTo(IShape[] array)
        {
            _innerList.CopyTo(array);
        }

        #endregion


        /// <summary>
        /// 清空
        /// </summary>
        public virtual void Clear()
        {
            foreach (IShape shp in _innerList)
            {
                Remove(shp);
            }
            _innerList.Clear();
        }

        
        /// <summary>
        /// 包含
        /// </summary>
        /// <param name="shp"></param>
        /// <returns></returns>
        public virtual bool Contains(IShape shp)
        {
            return _innerList.Contains(shp);
        }

        #region IndexOf

        /// <summary>
        /// 
        /// </summary>
        /// <param name="shp"></param>
        /// <returns></returns>
        public virtual int IndexOf(IShape shp)
        {
            return _innerList.IndexOf(shp);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="shp"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        public virtual int IndexOf(IShape shp, int index)
        {
            return _innerList.IndexOf(shp, index);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="shp"></param>
        /// <param name="index"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public virtual int IndexOf(IShape shp, int index, int count)
        {
            return _innerList.IndexOf(shp, index, count);
        }

        #endregion


        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public IEnumerator<IShape> GetEnumerator()
        {
            return _innerList.GetEnumerator();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return _innerList.GetEnumerator();
        }


        #endregion




    }
}
